﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;

namespace SimpleNodeBasedEditor
{
    public class BaseWindowRenamePopWindow : EditorWindow
    {

        private string nameText = "";
        private Action<string> onClick;
        public void Init(Action<string> m_callback, string title)
        {
            onClick = m_callback;
            titleContent.text = title;
        }
        private void OnGUI()
        {

            GUILayout.Label("新名称");
            nameText = GUILayout.TextField(nameText);
            if (GUILayout.Button("确定") && !string.IsNullOrEmpty(nameText))
            {
                Close();
                if (null != onClick)
                {
                    onClick(nameText);
                }

            }
            this.Focus();
        }
    }
    public enum NodeEditorMenuType
    {
        CreateNewNode = 1,
        DeleteNode

    }
    /// <summary>
    /// 每个分页的节点管理
    /// </summary>
    public class BaseNodeWindow
    {
        private int m_curSelectId = -1;
        public int CurSelectId
        {
            get
            {
                return m_curSelectId;
            }

            set
            {
                m_curSelectId = value;
            }
        }
        private BaseNodeWindowData m_windowData;
        public BaseNodeWindowData WindowData
        {
            get
            {
                return m_windowData;
            }

            set
            {
                m_windowData = value;
            }
        }
        protected Dictionary<int, BaseNodeView> m_NodeViewDict = new Dictionary<int, BaseNodeView>();
        /// <summary>
        /// 是否释放自身的连线
        /// </summary>
        public bool ReleaseSelect = false;
        /// <summary>
        /// 加载本页面的所有节点的数据-已有数据会调用此方法
        /// </summary>
        /// <param name="PageId"></param>
        public virtual void LoadData(int PageId)
        {

            var scriptObj = EditorDataSaveUtilities.Instance.LoadPageScriptableObject(PageId);
            if (null != scriptObj)
            {
                LoadView(EditorDataSaveUtilities.Instance.ConvertToWindowData(scriptObj));
                return;
            }
            Debug.LogError("加载失败  窗口索引文件丢失 创建 测试view " + PageId);
            m_windowData = new BaseNodeWindowData();
            CreateTestView(PageId);
        }
        /// <summary>
        /// 新建数据会调用此方法
        /// </summary>
        /// <param name="pageId"></param>
        public virtual void CreateData(int pageId, string type)
        {
            m_windowData = new BaseNodeWindowData();
            m_windowData.PageId = pageId;
            m_windowData.WindowName = "新建窗口*";
            m_windowData.Counter = 0;
            m_windowData.WindowType = type;
            //强制打开一个选择文件夹路径的对话框
            OpenSaveDialog();
        }
        public void OnClick(int button)
        {
            if (button == 1)
            {
                BaseNodeView nodeView;
                if (!isOnAnyNodeView(Event.current.mousePosition, out nodeView))
                {
                    DrawMenu(false, null);
                }

            }
        }
        #region Draw UIElements
        protected virtual void DrawMenu(bool isOnNode, BaseNodeView nodeView)
        {
            GenericMenu menu = new GenericMenu();
            if (!isOnNode)
            {
                foreach (var item in BaseNodeTypes.GetAllNodesDict())
                {
                    object[] userData = new object[3];
                    userData[0] = NodeEditorMenuType.CreateNewNode;
                    userData[1] = item.Key;
                    userData[2] = Event.current.mousePosition;
                    menu.AddItem(new GUIContent("新建节点/" + item.Value), false, ProcessMenu, userData);
                }

            }
            else
            {
                object[] userData = new object[3];
                userData[0] = NodeEditorMenuType.DeleteNode;
                userData[1] = nodeView;
                userData[2] = Event.current.mousePosition;
                menu.AddItem(new GUIContent("删除节点"), false, ProcessMenu, userData);

            }
            menu.ShowAsContext();
        }
        protected virtual void ProcessMenu(object userData)
        {
            object[] param = (object[])userData;

            NodeEditorMenuType type = (NodeEditorMenuType)param[0];
            switch (type)
            {
                case NodeEditorMenuType.CreateNewNode:
                    {
                        Type nodeType = (Type)param[1];
                        var node = CreateNewNode(nodeType);
                        if (null != node)
                        {
                            node.SetCenterPosition((Vector2)param[2]);
                        }

                    }
                    break;
                case NodeEditorMenuType.DeleteNode:
                    {
                        BaseNodeView nodeView = (BaseNodeView)param[1];
                        if (nodeView != null)
                        {
                            DeleteNode(nodeView);
                        }
                    }

                    break;

            }

        }
        protected virtual void CreateTestView(int pageId)
        {
            //TestCode
            m_windowData.WindowName = "TempWindow" + pageId;
            m_windowData.PageId = pageId;
            var nodeA = CreateNewNode();
            if (nodeA != null)
            {
                nodeA.Data.LinkId = 2;
            }
            CreateNewNode();

        }
        /// <summary>
        /// 绘制窗口
        /// </summary>
        public virtual void DrawWindow()
        {
            if (null == WindowData)
            {
                Debug.LogError("当前窗口数据异常");
                return;
            }
            GUI.Label(new Rect(5, 10, 150, 15), "窗口Id:" + WindowData.PageId + "名称:" + WindowData.WindowName);
            if (GUI.Button(new Rect(160, 10, 200, 15), "更改名称"))
            {
                BaseWindowRenamePopWindow window = ScriptableObject.CreateInstance<BaseWindowRenamePopWindow>();
                window.Init((name) =>
                {
                    WindowData.WindowName = name;
                }, WindowData.WindowName);
                window.position = new Rect(Event.current.mousePosition, new Vector2(400, 80));
                window.ShowUtility();
            }
            GUI.Label(new Rect(5, 30, 200, 15), "当前选择Id:" + m_curSelectId);
            if (GUI.Button(new Rect(5, 50, 200, 15), "点击选择保存的路径"))
            {
                OpenSaveDialog();
            }
            GUI.Label(new Rect(230, 50, 200, 15), WindowData.SaveFolder);
            if (GUI.Button(new Rect(5, 70, 200, 15), "SaveAll"))
            {
                OnClickSaveButton();
            }
            if (GUI.Button(new Rect(5, 90, 200, 15), "Reload"))
            {
                OnClickReload();
            }
            DrawAllNodes();
        }
        protected virtual void DrawAllNodes()
        {
            //绘画窗口  
            foreach (var node in m_NodeViewDict.Values)
            {
                node.Data.windowRect = GUI.Window(node.Data.Id, node.Data.windowRect, node.DrawNode, node.Data.NodeName);
            }
        }
        protected virtual void OnClickSaveButton()
        {
            NodeWindowManager.Instance.SaveCurrentPage();

        }
        protected virtual void OnClickReload()
        {
            LoadData(WindowData.PageId);

        }
        protected virtual void OpenSaveDialog()
        {
            string savePath = UnityEditor.EditorUtility.OpenFolderPanel("选择保存的文件夹", Application.dataPath, "windowFolder");
            if (null != savePath)
            {
                WindowData.SaveFolder = savePath;
                WindowData.SaveFolder = WindowData.SaveFolder.Substring(WindowData.SaveFolder.IndexOf("Assets/") + 7);

            }
        }
        public virtual void LinkNode()
        {

            foreach (var node in m_NodeViewDict.Values)
            {
                if (ReleaseSelect && CurSelectId == node.Data.Id)
                {
                    NodeLineManager.Instance.DrawNodeCurve(node.Data.windowRect, new Rect(Event.current.mousePosition, new Vector2(2, 2)), Color.green);
                    continue;
                }
                int linkId = node.Data.LinkId;
                var nextNode = GetNode(linkId);
                if (null != nextNode)
                {
                    NodeLineManager.Instance.DrawNodeCurve(node.Data.windowRect, nextNode.Data.windowRect, Color.red);
                }
                else
                {
                    node.Data.LinkId = -1;
                }
            }
        }

        #endregion


        #region HelpMethod
        /// <summary>
        /// view层 保存到数据 
        /// </summary>
        public virtual void SaveToData()
        {

            WindowData.NodeDict.Clear();
            foreach (var key in m_NodeViewDict.Keys)
            {
                var view = m_NodeViewDict[key];
                view.WillSaveData(this);
                WindowData.NodeDict.Add(view.Data);
            }
        }
        /// <summary>
        /// 加载数据
        /// </summary>
        /// <param name="baseNodeWindowData">已经反序列化到内存中的window数据对象</param>
        public virtual void LoadView(BaseNodeWindowData baseNodeWindowData)
        {
            m_NodeViewDict.Clear();
            if (null == baseNodeWindowData)
            {
                return;
            }
            WindowData = baseNodeWindowData;
            foreach (var data in baseNodeWindowData.NodeDict)
            {
                if (null != data)
                {
                    BaseNodeView nodeView = BaseNodeView.CreateByType(data.NodeViewType);
                    nodeView.LoadData(new BaseNodeData(data));
                    if (!m_NodeViewDict.ContainsKey(data.Id))
                    {
                        m_NodeViewDict.Add(data.Id, nodeView);
                    }
                }

            }

        }
        public virtual BaseNodeView GetNode(int id)
        {
            if (id == -1)
            {

                return null;
            }
            if (m_NodeViewDict.ContainsKey(id))
            {
                BaseNodeView nodeObj = m_NodeViewDict[id];
                return nodeObj;
            }
            else
            {
                Debug.LogError("Id Dosent Exist！ " + id);
                return null;
            }
        }
        public virtual BaseNodeView CreateNewNode(Type type = null)
        {
            if (type == null)
            {
                type = typeof(BaseNodeView);
            }
            BaseNodeView nodeObj = (BaseNodeView)Activator.CreateInstance(type);
            int id = ++m_windowData.Counter;
            nodeObj.CreateData(id, type.ToString());
            if (!m_NodeViewDict.ContainsKey(id))
            {
                m_NodeViewDict.Add(id, nodeObj);
            }
            else
            {
                Debug.LogError("Id Error!!!" + id);
            }
            return nodeObj;
        }
        public virtual void DeleteNode(int Id)
        {
            if (m_NodeViewDict.ContainsKey(Id))
            {
                BaseNodeView nodeView = m_NodeViewDict[Id];
                nodeView.Release();
                m_NodeViewDict.Remove(Id);
            }
            else
            {
                Debug.LogError("Id Dosent Exist！ " + Id);
            }
        }
        protected virtual void DeleteNode(BaseNodeView nodeView)
        {
            if (nodeView != null)
            {
                nodeView.Release();
                m_NodeViewDict.Remove(nodeView.Data.Id);
            }
        }
        public virtual void SetSelectId(int id)
        {
            m_curSelectId = id;
        }

        public virtual bool isOnAnyNodeView(Vector2 position, out BaseNodeView findedView)
        {
            if (null != m_NodeViewDict)
            {
                foreach (var view in m_NodeViewDict.Values)
                {
                    if (null != view)
                    {
                        if (view.Data.windowRect.Contains(position))
                        {
                            findedView = view;
                            return true;
                        }
                    }
                }
            }
            findedView = null;

            return false;
        }
        #endregion

        public static BaseNodeWindow CreateNodeWindow(string windowType)
        {
            BaseNodeWindow windowObj = (BaseNodeWindow)ReflectionUtilities.CreateInstance(windowType);
            if (windowObj == null)
            {
                Debug.LogError("创建实例失败 " + windowType);
            }
            return (BaseNodeWindow)windowObj;
        }
        public static BaseNodeWindow CreateNodeWindow(int pageId)
        {
            NodeWindowScriptableObject scriptableObject = EditorDataSaveUtilities.Instance.LoadPageScriptableObject(pageId);
            BaseNodeWindow windowObj = (BaseNodeWindow)ReflectionUtilities.CreateInstance(scriptableObject.WindowType);
            if (windowObj == null)
            {
                Debug.LogError("创建实例失败 " + scriptableObject.WindowType);
            }
            return (BaseNodeWindow)windowObj;
        }

    }

}